﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Runtime.Serialization;
using System.Windows.Forms;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using OpenComposite.Workflow.Properties;

namespace OpenComposite.Workflow
{
	[Designer(typeof(JumpSplitDesigner))]
	[ToolboxItem(typeof(WhileSplitToolboxItem))]
	[ToolboxBitmap(typeof(resfinder), "OpenComposite.Workflow.Resources.jump.PNG")]
	public class JumpSplitActivity : Activity
	{
		public static readonly DependencyProperty ConditionProperty = DependencyProperty.Register("Condition", typeof(ActivityCondition), typeof(JumpSplitActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata));
		public ActivityCondition Condition
		{
			get { return GetValue(ConditionProperty) as ActivityCondition; }

            set
            {
                SetValue(ConditionProperty, value);
                //EventHandler tmp = ConditionChanged;
                //if ( tmp != null ) {
                //    tmp(this, EventArgs.Empty);
                //}
            }
        }

        public JumpSplitActivity()
        {
        }

		internal event EventHandler ConditionChanged;

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            return base.Execute(executionContext);
        }
    }

	[ActivityDesignerTheme(typeof(JumpSplitActivityTheme))]
	public class JumpSplitDesigner : ActivityDesigner
	{
		private const int height = 40;
		private const int width = 40;
		private Size _size = new Size(width, height);
		private Pen outerSymbolPen = new Pen(Brushes.MediumBlue, 2.0F);
		private Pen innerSymbolPenM = new Pen(Brushes.Black, 3.0F);
		private bool _isDragging = false;
		private SizeF s = Size.Empty;
		private Font _textFont = new Font(FontFamily.GenericSansSerif, 11.0F, FontStyle.Bold);
        //private GraphicsPath _borderPath;

        public override Size MinimumSize
        {
            get { return _size; }
        }

        public override Size Size
        {
            get { return _size; }
            set { base.Size = value; }
        }

        protected override void Initialize(Activity activity)
        {
            base.Initialize(activity);
            JumpSplitActivity jump = activity as JumpSplitActivity;
            if ( jump != null ) {
                jump.ConditionChanged += new EventHandler(jump_ConditionChanged);
            }
        }

        protected override void Dispose(bool disposing)
        {
            JumpSplitActivity jump = this.Activity as JumpSplitActivity;
            if ( jump != null ) {
                jump.ConditionChanged -= jump_ConditionChanged;
            }
            base.Dispose(disposing);
        }

        void jump_ConditionChanged(object sender, EventArgs e)
        {
        }

		protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e)
		{
			base.OnLayoutPosition(e);
            //CreateBorder();
		}

		protected override void OnPaint(ActivityDesignerPaintEventArgs e)
		{
			if ( !IsVisible )
				return;

			base.OnPaint(e);

			if ( s == SizeF.Empty )
				s = e.Graphics.MeasureString("J", _textFont);

			int width = 10;
			int arrowWidth = 4;
			int height = 30;
			int padding = 10;

			Point center = WorkflowHelpers.GetCenter(Bounds);

			e.Graphics.DrawString("J",
				_textFont,
				e.DesignerTheme.ForegroundBrush,
				new PointF(center.X - width - ( s.Width / 2 ),
					center.Y - ( s.Height / 2 )));

			e.Graphics.DrawArc(e.DesignerTheme.ForegroundPen, new Rectangle(
				new Point(Bounds.Right - width - padding, center.Y - 13),
				new Size(width, height)), 130, 200);

			e.Graphics.FillPolygon(Brushes.Black,
				new Point[]{
			        new Point(Bounds.Right-arrowWidth/2-padding,center.Y-2),
			        new Point(Bounds.Right+arrowWidth/2-padding,center.Y-2),
			        new Point(Bounds.Right-padding,center.Y+4)
			    }, System.Drawing.Drawing2D.FillMode.Winding);


		}

        protected override Rectangle TextRectangle
        {
            get { return Rectangle.Empty; }
        }

        protected override Rectangle ImageRectangle
        {
            get { return Rectangle.Empty; }
        }

        //private void CreateBorder()
        //{
        //    int width = this.Size.Width;
        //    int height = this.Size.Height;
        //    int x = this.Location.X;
        //    int y = this.Location.Y;
        //    int dia = 15;

        //    _borderPath = new GraphicsPath();

        //    _borderPath.AddArc(x, y, dia, dia, 180, 90);
        //    _borderPath.AddArc(x + width - dia, y, dia, dia, 270, 90);
        //    _borderPath.AddArc(x + width - dia, y + height - dia, dia, dia, 0, 90);
        //    _borderPath.AddArc(x, y + height - dia, dia, dia, 90, 90);
        //    _borderPath.CloseAllFigures();
        //}

		protected override void OnMouseMove(MouseEventArgs e)
		{
			if ( e.Button == MouseButtons.Left ) {
				if ( !_isDragging ) {
					HorizontalWorkflowDesigner root = WorkflowHelpers.GetRootDesigner(this) as HorizontalWorkflowDesigner;
					if ( !root.Workflow.WhileConnectors.Exists(delegate(FreeConnector conn)
					{
						if ( conn.Start == this.Activity.QualifiedName )
							return true;
						else
							return false;
					}) ) {
						_isDragging = true;
						root.DraggedActivity = this.Activity;
					} else {
						return;
					}
				}
			}
			base.OnMouseMove(e);
		}

		protected override void OnMouseLeave()
		{
			_isDragging = false;
			base.OnMouseLeave();
		}

        protected override void OnActivityChanged(ActivityChangedEventArgs e)
        {
            if ( e.Member != null && e.Member.Name == "Name" ) {
                if ( e.NewValue != e.OldValue && e.OldValue != null && e.NewValue != null ) {
                    HorizontalWorkflowActivity act = WorkflowHelpers.GetRootActivity(this.Activity) as HorizontalWorkflowActivity;
                    foreach ( FreeConnector conn in act.WhileConnectors ) {
                        if ( conn.Start == e.OldValue.ToString() ) {
                            conn.Start = e.NewValue.ToString();
                            break;
                        }
                    }
                }
            }
            base.OnActivityChanged(e);
        }
	}

	public class JumpSplitActivityTheme : ActivityDesignerTheme
	{
		public JumpSplitActivityTheme(WorkflowTheme theme)
			: base(theme)
		{
			this.BorderColor = Color.ForestGreen;
			this.BackColorStart = Color.White;
			this.BackColorEnd = Color.YellowGreen;
			this.BackgroundStyle = LinearGradientMode.ForwardDiagonal;
		}
	}

	[Serializable]
	public class WhileSplitToolboxItem : ActivityToolboxItem
	{
		public WhileSplitToolboxItem(Type type)
			: base(type)
		{
			this.DisplayName = "Jump";
		}

		private WhileSplitToolboxItem(SerializationInfo info, StreamingContext context)
		{
			Deserialize(info, context);
		}
	}

	#region Jump Group

	[Designer(typeof(JumpSplitGroupDesigner))]
	[ToolboxItem(typeof(JumpSplitGroupToolboxItem))]
	[ToolboxBitmap(typeof(resfinder), "OpenComposite.Workflow.Resources.jump.PNG")]
	public class JumpSplitGroupActivity : HorizontalSequenceActivity
	{
		protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
		{
			return base.Execute(executionContext);
		}
	}

	public class JumpSplitGroupDesigner : HorizontalSequenceDesigner
	{
		private const int widht = 40;
		private const int height = 40;
		private readonly Size _minimumSize = new Size(widht, height);
		private Rectangle _ExpandButtonRectangle = new Rectangle(0, 0, 8, 8);
		private Font _textFont = new Font(FontFamily.GenericSansSerif, 11.0F, FontStyle.Bold);
		private SizeF s = Size.Empty;

		protected override void OnPaint(ActivityDesignerPaintEventArgs e)
		{
			if ( !IsVisible )
				return;

			if ( Expanded ) {
				base.OnPaint(e);

				using ( Pen dashPen = new Pen(Color.SlateGray) { DashStyle = DashStyle.Dash } ) {
					ActivityDesignerPaint.DrawRoundedRectangle(e.Graphics, dashPen, Bounds, 10);
				}
				PaintContainedDesigners(e);

			} else {
				GraphicsPath shape = ActivityDesignerPaint.GetRoundedRectanglePath(Bounds, 10);
				using ( LinearGradientBrush brush = new LinearGradientBrush(Bounds, Color.White, Color.YellowGreen, LinearGradientMode.ForwardDiagonal) ) {
					e.Graphics.FillPath(brush, shape);
					e.Graphics.DrawPath(e.DesignerTheme.BorderPen, shape);
				}

				if ( s == SizeF.Empty )
					s = e.Graphics.MeasureString("J", _textFont);


				int width = 10;
				int arrowWidth = 4;
				int height = 30;
				int padding = 10;
				Point center = WorkflowHelpers.GetCenter(Bounds);

				e.Graphics.DrawString("J",
					_textFont,
					e.DesignerTheme.ForegroundBrush,
					new PointF(center.X - width - ( s.Width / 2 ),
						center.Y - ( s.Height / 2 )));

				e.Graphics.DrawArc(e.DesignerTheme.ForegroundPen, new Rectangle(
					new Point(Bounds.Right - width - padding, center.Y - 13),
					new Size(width, height)), 130, 200);

				e.Graphics.FillPolygon(Brushes.Black,
					new Point[]{
						new Point(Bounds.Right-arrowWidth/2-padding,center.Y-2),
						new Point(Bounds.Right+arrowWidth/2-padding,center.Y-2),
						new Point(Bounds.Right-padding,center.Y+4)
					}, System.Drawing.Drawing2D.FillMode.Winding);

				//e.Graphics.DrawRectangle(e.DesignerTheme.ForegroundPen, Bounds);
				//e.Graphics.DrawString(Activity.QualifiedName, e.DesignerTheme.Font,
				//    e.DesignerTheme.ForegroundBrush,
				//    Bounds.Left + 20.0F,
				//    WorkflowHelpers.GetCenter(Bounds).Y - e.Graphics.MeasureString(Activity.QualifiedName, e.DesignerTheme.Font).Height / 2);
			}

			ActivityDesignerPaint.DrawExpandButton(e.Graphics, ExpandButtonRectangle, Expanded, (CompositeDesignerTheme)e.DesignerTheme);


		}

		protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e)
		{
			base.OnLayoutPosition(e);

			if ( this.Activity.QualifiedName != this.Activity.GetType().Name ) {
				if ( ContainedDesigners.Count == 0 ) {
					List<Activity> list = new List<Activity>();
					list.Add(new HorizontalSequenceActivity());
					ReadOnlyCollection<Activity> roc = new ReadOnlyCollection<Activity>(list);
					InsertActivities(HitTest(Location), roc);
				}

				ContainedDesigners[0].Location =
					new Point(ContainedDesigners[0].Location.X - 40,
						ContainedDesigners[0].Location.Y);

			}
		}

		protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
		{
			if ( !Expanded ) {
				return _minimumSize;
			} else {
				Size size = base.OnLayoutSize(e);
				size.Height += 5;
				size.Width -= 80;
				return size;
			}
		}

		protected override Rectangle ExpandButtonRectangle
		{
			get
			{
				if ( Expanded ) {
					_ExpandButtonRectangle.Location =
							new Point(Bounds.Left + 10, Bounds.Top + 10);
				} else {
					_ExpandButtonRectangle.Location =
						new Point(Bounds.Right - _ExpandButtonRectangle.Size.Width - 5,
							WorkflowHelpers.GetCenter(Bounds).Y + 7);
				}

				return _ExpandButtonRectangle;
			}
		}

		public override bool CanInsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
		{
			return false;
		}

		public override Size MinimumSize
		{
			get { return _minimumSize; }
		}

		public override void RemoveActivities(ReadOnlyCollection<Activity> activitiesToRemove)
		{
			List<Activity> list = new List<Activity>();
			list.Add(ContainedDesigners[0].Activity);
			ReadOnlyCollection<Activity> roc = new ReadOnlyCollection<Activity>(list);
			ParentDesigner.RemoveActivities(roc);
		}
	}

	[Serializable]
	public class JumpSplitGroupToolboxItem : ActivityToolboxItem
	{
		public JumpSplitGroupToolboxItem(Type type)
			: base(type)
		{
			this.DisplayName = "Jump Group";
		}

		private JumpSplitGroupToolboxItem(SerializationInfo info, StreamingContext context)
		{
			Deserialize(info, context);
		}
	}

	#endregion

}
